import json

from django.core.cache import cache
from django.db.utils import IntegrityError
from django.http import JsonResponse
from loguru import logger

from api.public_methods import response_json
from .models import MenuBarItems, MenuBarClass


# -------------------------------- 导航信息管理 --------------------------------
def menu_bar_search(request):
    # 查询导航信息
    try:
        name = request.GET.get('name')

        if name:
            sql = f"""
            SELECT
                a.id, a.menu_bar_name, a.menu_bar_order, a.menu_bar_url, a.menu_bar_icon, 
                b.menu_bar_class_name, b.menu_bar_class_order, b.menu_bar_class_icon
            FROM
                `menu_bar_items` AS a
                INNER JOIN menu_bar_class AS b ON a.menu_bar_class_id = b.id 
                AND ( a.menu_bar_name LIKE '%%{name}%%' OR a.menu_bar_url LIKE '%%{name}%%' ) 
            ORDER BY
                b.menu_bar_class_order ASC, a.menu_bar_order ASC
            """
        else:
            # 先查询缓存是否存在
            cache_key = 'database_search_cache:menu_bar_items'
            cache_result = cache.get(cache_key)
            if cache_result:
                return JsonResponse(response_json(code=0, message='查询成功', data=json.loads(cache_result)))
            else:
                sql = f"""
                SELECT
                    a.id, a.menu_bar_name, a.menu_bar_order, a.menu_bar_url, a.menu_bar_icon, 
                    b.menu_bar_class_name, b.menu_bar_class_order , b.menu_bar_class_icon
                FROM
                    `menu_bar_items` AS a
                    INNER JOIN menu_bar_class AS b ON a.menu_bar_class_id = b.id 
                ORDER BY
                    b.menu_bar_class_order ASC, a.menu_bar_order ASC
                """
        items_obj = MenuBarItems.objects.raw(sql)
        items_data_list = [item.__dict__ for item in items_obj]

        # 使用字典将查询结果按 'menu_bar_class' 字段归类
        grouped_results = {}
        for item in items_data_list:
            class_name = item['menu_bar_class_name']
            class_icon = item['menu_bar_class_icon']
            key = (class_name, class_icon)
            if class_name not in grouped_results:
                grouped_results[key] = []
            item.pop('menu_bar_order')
            item.pop('menu_bar_class_name')
            item.pop('menu_bar_class_order')
            item.pop('menu_bar_class_icon')
            item.pop('_state')
            grouped_results[key].append(item)

        # 格式化结果
        formatted_results = [
            {"class_name": class_name, "class_icon": class_icon, "items_data": items}
            for (class_name, class_icon), items in grouped_results.items()
        ]
        not name and cache.set(cache_key, json.dumps(formatted_results), timeout=86400)
        logger.info(formatted_results)
        return JsonResponse(response_json(code=0, message='查询成功', data=formatted_results))
    except AssertionError as e:
        logger.error(f'{e}')
        return JsonResponse(response_json(code=1, message=f'{e}'))
    except Exception as e:
        logger.exception(f'查询导航信息发生错误，{e}')
        return JsonResponse(response_json(code=1, message=f'查询导航信息发生错误，{e}'))


def menu_bar_add(request):
    # 添加导航信息
    try:
        post_json = json.loads(request.body)
        menu_bar_name = post_json.get('menu_bar_name')
        menu_bar_order = post_json.get('menu_bar_order')
        menu_bar_url = post_json.get('menu_bar_url')
        menu_bar_icon = post_json.get('menu_bar_icon')
        menu_bar_class_id = post_json.get('menu_bar_class_id')
        need_login = post_json.get('need_login')

        assert menu_bar_name, '参数menu_bar_name不存在'
        assert menu_bar_order is None or isinstance(menu_bar_order, int), '参数menu_bar_order不符合要求'
        assert menu_bar_url, '参数menu_bar_url不存在'
        assert menu_bar_icon, '参数menu_bar_icon不存在'
        assert menu_bar_class_id is None or isinstance(menu_bar_class_id, int), '参数menu_bar_class不存在'
        assert need_login is not None, '参数need_login不存在'
        MenuBarClass.objects.get(id=menu_bar_class_id)

        menu_bar_obj = MenuBarItems.objects.create(
            menu_bar_name=menu_bar_name,
            menu_bar_order=menu_bar_order,
            menu_bar_url=menu_bar_url,
            menu_bar_icon=menu_bar_icon,
            menu_bar_class_id=menu_bar_class_id,
            need_login=need_login
        )
        return JsonResponse(response_json(code=0, message='添加成功', data=menu_bar_obj.id))
    except IntegrityError:
        return JsonResponse(response_json(code=1, message='添加失败，名称或链接地址已存在'))
    except MenuBarClass.DoesNotExist:
        return JsonResponse(response_json(code=1, message='添加失败，导航分类不存在'))
    except AssertionError as e:
        logger.error(f'{e}')
        return JsonResponse(response_json(code=1, message=f'{e}'))
    except Exception as e:
        logger.exception(f'添加导航信息发生错误，{e}')
        return JsonResponse(response_json(code=1, message=f'添加导航信息发生错误，{e}'))


def menu_bar_modify(request):
    # 修改导航信息
    try:
        post_json = json.loads(request.body)
        menu_id = post_json.get('menu_id')
        assert menu_id, '参数menu_id不存在'

        menu_bar_name = post_json.get('menu_bar_name')
        menu_bar_order = post_json.get('menu_bar_order')
        menu_bar_url = post_json.get('menu_bar_url')
        menu_bar_icon = post_json.get('menu_bar_icon')
        menu_bar_class_id = post_json.get('menu_bar_class_id')
        need_login = post_json.get('need_login')

        info_obj = MenuBarItems.objects.get(id=menu_id)
        if menu_bar_name:
            info_obj.menu_bar_name = menu_bar_name
        if menu_bar_order and isinstance(menu_bar_order, int):
            info_obj.menu_bar_order = menu_bar_order
        if menu_bar_url:
            info_obj.menu_bar_url = menu_bar_url
        if menu_bar_icon:
            info_obj.menu_bar_icon = menu_bar_icon
        if menu_bar_class_id:
            assert menu_bar_class_id is None or isinstance(menu_bar_class_id, int), '参数menu_bar_class不存在或不是整数'
            MenuBarClass.objects.get(id=menu_bar_class_id)
            info_obj.menu_bar_class_id = menu_bar_class_id
        if need_login is not None:
            info_obj.need_login = need_login
        info_obj.save()
        return JsonResponse(response_json(code=0, message='导航信息修改成功'))
    except IntegrityError as e:
        return JsonResponse(response_json(code=1, message='修改失败，名称或链接地址已存在'))
    except MenuBarItems.DoesNotExist:
        return JsonResponse(response_json(code=1, message='修改失败，该导航信息不存在'))
    except MenuBarClass.DoesNotExist:
        return JsonResponse(response_json(code=1, message='修改失败，导航分类不存在'))
    except AssertionError as e:
        logger.error(f'{e}')
        return JsonResponse(response_json(code=1, message=f'{e}'))
    except Exception as e:
        logger.exception(f'修改导航信息发生错误，{e}')
        return JsonResponse(response_json(code=1, message=f'修改导航信息发生错误，{e}'))


def menu_bar_delete(request):
    # 删除导航信息
    try:
        post_json = json.loads(request.body)
        menu_id = post_json.get('menu_id')
        assert menu_id, '参数menu_id不存在'
        # 根据menu_id删除导航信息
        MenuBarItems.objects.get(id=menu_id).delete()
        return JsonResponse(response_json(code=0, message='删除成功'))
    except MenuBarItems.DoesNotExist:
        return JsonResponse(response_json(code=1, message='删除失败，该导航信息不存在'))
    except AssertionError as e:
        logger.error(f'{e}')
        return JsonResponse(response_json(code=1, message=f'{e}'))
    except Exception as e:
        logger.exception(f'删除导航信息发生错误，{e}')
        return JsonResponse(response_json(code=1, message=f'删除导航信息发生错误，{e}'))


# -------------------------------- 导航分类管理 --------------------------------
def menu_bar_class_search(request):
    # 查询导航分类
    try:
        cache_key = 'database_search_cache:menu_bar_class'
        cache_result = cache.get(cache_key)
        if cache_result:
            return JsonResponse(response_json(code=0, message='查询成功', data=json.loads(cache_result)))
        else:
            class_obj = MenuBarClass.objects.all()
            data = [i.to_json() for i in class_obj]
            cache.set(cache_key, json.dumps(data), timeout=86400)
            return JsonResponse(response_json(code=0, message='查询成功', data=data))
    except AssertionError as e:
        logger.error(f'{e}')
        return JsonResponse(response_json(code=1, message=f'{e}'))
    except Exception as e:
        logger.exception(f'查询导航分类信息发生错误，{e}')
        return JsonResponse(response_json(code=1, message=f'查询导航分类信息发生错误，{e}'))


def menu_bar_class_add(request):
    # 添加导航分类
    try:
        post_json = json.loads(request.body)
        menu_bar_class_name = post_json.get('menu_bar_class_name')
        menu_bar_class_order = post_json.get('menu_bar_class_order')
        menu_bar_class_icon = post_json.get('menu_bar_class_icon')
        assert menu_bar_class_name, '参数menu_bar_class_name不存在'
        assert menu_bar_class_order and isinstance(menu_bar_class_order, int), '参数menu_bar_class_order不存在或不是整数'
        assert menu_bar_class_icon, '参数menu_bar_class_icon不存在'
        class_obj = MenuBarClass.objects.create(
            menu_bar_class_name=menu_bar_class_name,
            menu_bar_class_order=menu_bar_class_order,
            menu_bar_class_icon=menu_bar_class_icon
        )
        return JsonResponse(response_json(code=0, message='添加成功', data=class_obj.id))
    except IntegrityError:
        return JsonResponse(response_json(code=1, message='添加失败，名称已存在'))
    except AssertionError as e:
        logger.error(f'{e}')
        return JsonResponse(response_json(code=1, message=f'{e}'))
    except Exception as e:
        logger.exception(f'添加导航分类信息发生错误，{e}')
        return JsonResponse(response_json(code=1, message=f'添加导航分类信息发生错误，{e}'))


def menu_bar_class_modify(request):
    # 修改导航分类
    try:
        post_json = json.loads(request.body)
        menu_bar_class_id = post_json.get('menu_bar_class_id')
        assert menu_bar_class_id, '参数menu_bar_class_id不存在'
        menu_bar_class_name = post_json.get('menu_bar_class_name')
        menu_bar_class_order = post_json.get('menu_bar_class_order')
        menu_bar_class_icon = post_json.get('menu_bar_class_icon')

        class_obj = MenuBarClass.objects.get(id=menu_bar_class_id)
        if menu_bar_class_name:
            class_obj.menu_bar_class_name = menu_bar_class_name
        if menu_bar_class_order:
            assert isinstance(menu_bar_class_order, int), '参数menu_bar_class_order不存在或不是整数'
            class_obj.menu_bar_class_order = menu_bar_class_order
        if menu_bar_class_icon:
            class_obj.menu_bar_class_icon = menu_bar_class_icon
        class_obj.save()
        return JsonResponse(response_json(code=0, message='修改成功'))
    except MenuBarClass.DoesNotExist:
        return JsonResponse(response_json(code=1, message='修改失败，该导航分类不存在'))
    except AssertionError as e:
        logger.error(f'{e}')
        return JsonResponse(response_json(code=1, message=f'{e}'))
    except Exception as e:
        logger.exception(f'修改导航分类信息发生错误，{e}')
        return JsonResponse(response_json(code=1, message=f'修改导航分类信息发生错误，{e}'))


def menu_bar_class_delete(request):
    # 删除导航分类
    try:
        post_json = json.loads(request.body)
        menu_bar_class_id = post_json.get('menu_bar_class_id')
        assert menu_bar_class_id, '参数menu_bar_class_id不存在'
        MenuBarClass.objects.get(id=menu_bar_class_id).delete()
        return JsonResponse(response_json(code=0, message='删除成功'))
    except MenuBarClass.DoesNotExist:
        return JsonResponse(response_json(code=1, message='删除失败，该导航分类不存在'))
    except AssertionError as e:
        logger.error(f'{e}')
        return JsonResponse(response_json(code=1, message=f'{e}'))
    except Exception as e:
        logger.exception(f'删除导航分类信息发生错误，{e}')
        return JsonResponse(response_json(code=1, message=f'删除导航分类信息发生错误，{e}'))
